using Assets.Common.Math;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using static UnityEngine.InputSystem.InputAction;

public class UnityClickInteraction : MonoBehaviour
{
    [SerializeField]
    InputAction _clickInputAction;
    [SerializeField]
    LayerMask _canInteractionLayer;
    //ui显示holding数据
    [SerializeField]
    private Fraction<float> _performedTimer;

    private RaycastHit _lastHit;
    //触发案件检测的条件
    //[SerializeReference]
    //private List<Condition<Transform>> _enableConditions = new List<Condition<Transform>>();
    private Predicate<Transform> _enableConditions = x => true;
    public UnityEvent OnStarted;
    public UnityEvent OnPerformed;
    public UnityEvent OnCancel;

    public UnityEvent OnPhasePerformed;
    private void OnEnable()
    {
        _clickInputAction.Enable();


    }
    private void OnDisable()
    {
        _clickInputAction.Disable();
    }

    private void Start()
    {
        _clickInputAction.started += InputStarted;
        _clickInputAction.performed += InputPerformed;
        _clickInputAction.canceled += InputCanceled;
    }

    //debug
    int _performedCnt; int _canceledCnt; int _startedCnt;
    //触发hold的计时显示，手动设置成hold事件的事件
    public float PerformedProgress { get => _performedTimer.Progress(); }

    public RaycastHit LastHit { get => _lastHit;}
    public Fraction<float> PerformedTimer { get => _performedTimer; }

    private RaycastHit[] _checkHits = new RaycastHit[3];
    private void InputStarted(CallbackContext context)
    {
        _performedTimer.Reset();
        OnStarted.Invoke();
    }


    private void InputPerformed(CallbackContext context)
    {
        _performedTimer.Reset();
    }

    private void InputCanceled(CallbackContext context)
    {
        _performedTimer.Reset();
        OnCancel.Invoke();
    }
    void HandleCheckClickIntaction()
    {
        //查找可点击执行的物体
        var ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        var hitCount = Physics.RaycastNonAlloc(ray, _checkHits, 999f, _canInteractionLayer);
        for (int i = 0; i < hitCount; i++)
        {
            var hit = _checkHits[i];
            if (_enableConditions.Invoke(hit.collider.transform) == true)
            {
                _clickInputAction.Enable();
                _lastHit = hit;
                return;
            }
        }
        _clickInputAction.Disable();
    }
    public void ResetInput() 
    {
        _clickInputAction.Disable();
        _clickInputAction.Enable();
    }
    public void RegistCondition(Predicate<Transform> predicate)
    {
        _enableConditions = predicate;
    }
    private void Update()
    {
        if (EventSystem.current.IsPointerOverGameObject()
            && EventSystem.current.currentSelectedGameObject != null
            ) return;

        switch (_clickInputAction.phase)
        {
            case InputActionPhase.Disabled:
                HandleCheckClickIntaction();
                break;
            case InputActionPhase.Waiting:
                HandleCheckClickIntaction();
                break;
            case InputActionPhase.Started:
                break;
            case InputActionPhase.Performed:
                _performedTimer.Member += Time.deltaTime;
                OnPhasePerformed.Invoke();
                break;
            case InputActionPhase.Canceled:
                break;
            default:
                break;
        }
        Debug.Log(_clickInputAction.phase.ToString());
    }
}
